Skip to content

docs(ci): re-measure two stale reason comments in lint.yml (#15537, #15569) - #15756

Merged
baozhoutao merged 2 commits into
mainfrom
claude/issue-15537-15569-lint-yml-stale-comments
Sep 5, 2026
Merged

docs(ci): re-measure two stale reason comments in lint.yml (#15537, #15569)#15756
baozhoutao merged 2 commits into
mainfrom
claude/issue-15537-15569-lint-yml-stale-comments

Conversation

@claude

@claude claude Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Fixes #15537
Fixes #15569

Two reason comments in .github/workflows/lint.yml state measurements that no
longer describe the tree. Both are re-measured here and corrected to the reading
taken on this branch. Comments only — no command, no step name and no YAML
structure moves.


1. PM half-state sweeper self-test — "exactly ONE hint" (#15537)

The step justified pointing straight at the script, with no gate file in between,
on this reading: "this script yields exactly ONE hint, the repo slug in its API
base, which is not a repo path and covers no input path […] So the pollution that
forced a separate file there does not exist here."

Measured on the branch base (worktree at 95bf71449), exit codes captured before
any pipe:

$ node -e "const m = await import('./scripts/pm/dispatch-gates.mjs'); const fs = await import('node:fs'); console.log(JSON.stringify(m.extractWatchHints(fs.readFileSync('scripts/pm/check-half-states.mjs','utf8'), 'scripts/pm/check-half-states.mjs')))" --input-type=module
EXIT=0
["objectstack-ai/objectstack",".changeset","scripts/pm/check-half-states.mjs","owner/name"]

$ node -e "const m = await import('./scripts/pm/dispatch-gates.mjs'); console.log(m.hintCovers('.changeset', '.changeset/foo.md'))" --input-type=module
EXIT=0
true

$ node scripts/pm/dispatch-gates.mjs --commands .changeset/foo.md --repo objectstack-ai/objectstack | grep -c 'check:pm-half-states'
1

Four hints, not one. And the routing is by PATH MATCH, not by a whole-tree
declaration — the reason line says so itself:

$ node scripts/pm/dispatch-gates.mjs .changeset/foo.md --repo objectstack-ai/objectstack
EXIT=0
  - pnpm check:pm-half-states   [lint.yml]   matched via .changeset/foo.md ⇢ gate source '.changeset'

Coverage of each hint counted over git ls-files, so the comment can say which
hints are inert rather than asserting it:

"objectstack-ai/objectstack"          => covers 0 tracked file(s)
".changeset"                          => covers 84 tracked file(s)
"scripts/pm/check-half-states.mjs"    => covers 1 tracked file(s)   (itself)
"owner/name"                          => covers 0 tracked file(s)

Provenance of the two surviving slug-shaped hints, checked rather than assumed —
owner/name survives the module-body masking because it is not only prose:

scripts/pm/check-half-states.mjs:903    export const DEFAULT_SWEEP_REPO = 'objectstack-ai/objectstack';
scripts/pm/check-half-states.mjs:905    /** `owner/name`, GitHub's own character set for both halves. */
scripts/pm/check-half-states.mjs:6544   export const H36_SHARED_PREFIX_NOISE = Object.freeze(['.changeset/']);
scripts/pm/check-half-states.mjs:18383  '`owner/name` repository. Refusing to fall back to a different board — a report about '

What the comment now says. Four hints, named; three inert against this tree
with their measured coverage; the fourth (.changeset, from the noise-floor
constant H36_SHARED_PREFIX_NOISE, where the spelling exists to EXCLUDE a path
from pairing) DOES derive this step onto every changeset-adding card. Accepted
as-is, and the direct-entry argument is restated on that reading rather than
left resting on the withdrawn one: the "no pollution here" half is explicitly
WITHDRAWN, and what remains is that the routing costs a card one offline
self-test (no network, no token, ~0.05s, green) rather than the fan-out of
MATCHED leads across unrelated gates that forced a gate file next door.

Neither scripts/pm/check-half-states.mjs nor scripts/pm/dispatch-gates.mjs is
touched (the latter is a hot file of PR #15737).

2. Swallow-census control families — "four declared, three in gated" (#15569)

The block said measure-durability-swallow-family.mjs "declares four control
families"
and that "--self-test=gated runs RESOLUTION + NEGATIVE +
REGRESSION"
, closing with "The three wired families cannot be destroyed by a
successful repair"
.

The card's recollection was six declared / five in gated. Verified rather
than copied, and the card is off by one in both halves
— its own bullet list
enumerates seven. Read from the instrument, at 95bf71449:

$ sed -n '2102,2117p' scripts/measure-durability-swallow-family.mjs
  if (gated) {
    process.stdout.write(
      `${MEASUREMENT_BANNER}\n`
      + '✓ measure-durability-swallow-family self-test, gated families (#13919): '
      + `${NEGATIVE_CONTROLS.length} negative control(s) yield none, `
      + `${REGRESSION_CONTROLS.length} regression control(s) stay clear, `
      + `${RESOLUTION_CONTROLS.length} resolution control(s) resolve as declared, `
      + `${DETERMINED.size} DETERMINED register row(s) cross-check clean, `
      + `${copiedGateNames.length} copied gate-vocabulary name(s) match the gate's own declaration, `
      + `${WORKLIST_READING_CONTROLS.length} worklist reading(s) print as declared over a fixture population, `
      + `${members.length} member site(s) total\n`
      + `   ${POSITIVE_CONTROLS.length} positive control(s) are NOT asserted here, permanently: they pin `

gated names SIX families. The only one it drops is POSITIVE, and the drop is a
single expression:

$ grep -n 'gated ? \[\] : POSITIVE_CONTROLS' scripts/measure-durability-swallow-family.mjs
1922:  for (const control of gated ? [] : POSITIVE_CONTROLS) {

So: seven declared, six run in gated. Declaration sites:

367:  const POSITIVE_CONTROLS = [
432:  const NEGATIVE_CONTROLS = [
458:  const REGRESSION_CONTROLS = [
510:  const RESOLUTION_CONTROLS = [
640:  const WORKLIST_READING_CONTROLS = [
2025: the COPIED gate vocabulary (#15459), asserted in BOTH modes
1966: the DETERMINED register (#13886), asserted in BOTH modes

What the comment now says. The families are NAMED rather than counted, per the
ruling, so the next family added contradicts a list instead of an integer. The
asymmetry argument is kept in substance — gated, never a bare --self-test,
because POSITIVE_CONTROLS pin members of the #12981 worklist the repair
programme exists to REMOVE — and extended to cover the three newer families: the
control tables survive a repair because a repaired member moves from tier dark
to tier channelled and stays a member, and the three cross-checks never touch
membership at all. The census script itself is not touched.

NOT MEASURED by running it. pnpm check:swallow-census-controls cannot run
on this box:

$ pnpm check:swallow-census-controls
EXIT=1
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'typescript' imported from
  /home/user/objectstack-15537/scripts/measure-durability-swallow-family.mjs

That is a missing prerequisite, not a red gate — so the verdict line above is
quoted from the source that BUILDS it, and the family count is a static reading
of the declarations, which does not depend on the run. CI runs the real thing.


Comments-only proof

$ git diff --stat origin/main...HEAD
 .github/workflows/lint.yml | 75 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 59 insertions(+), 16 deletions(-)

$ git diff -U0 | grep -E '^[-+]' | grep -vE '^(\+\+\+|---)' | grep -vE '^[-+]\s*#'
(prints nothing — every changed line is a `#` comment line)

Stronger than the grep, since PyYAML is present here: the workflow is parsed
before and after and the parsed structures compare EQUAL.

$ python3 -c "..."   # yaml.safe_load of HEAD's copy vs the working copy
EXIT=0
after parses OK, jobs: 6
parsed structure identical to HEAD: True
  step: 'PM half-state sweeper self-test' | run: 'pnpm check:pm-half-states'
  step: 'Swallow-census control families (gated families only, never POSITIVE)' | run: 'pnpm check:swallow-census-controls'

Verification

Gate family derived from the tool, not guessed — and re-derived after the merge
of origin/main, on the FINAL tree:

$ node scripts/pm/dispatch-gates.mjs --changed --commands --repo objectstack-ai/objectstack
EXIT=0
dispatch-gates: gate list derived from the tree of 'objectstack-ai/objectstack' at commit 95bf71449
dispatch-gates: change set derived from git — 1 path(s) vs merge base 5b0c77909 of 'origin/main' and HEAD
37 command(s)

All 37 were run. Reading, at 95bf71449:

result count commands
green (EXIT=0) 18 check-position-name-fold-loaders (+--self-test), check-self-test-wired (+--self-test), check-self-test-workflow-commands (+--self-test), check-whole-set-label-write (+--self-test), docs-audit/check-drift-comment, pm/ci-failure --self-test, check:agent-test-spelling, check:declared-population-live, check:node-version, check:nul-bytes, check:pnpm-filter-targets, check:refd-timer-probe, check:type-check-coverage, check:watch-hint-literal
green (EXIT=0), re-run 1 check:pm-dispatch-gates1445 cases pass
⊘ NOT MEASURED 18 see below

pnpm check:pm-dispatch-gates first came back EXIT=1 with git check-ignore exited 128: fatal: pathspec '...' is beyond a symbolic link. That is this
box's node_modules symlink, not the diff: with the symlink moved aside the
same command is ✓ dispatch-gates self-test: 1445 cases pass. at EXIT=0. The
same symlink is why the first derivation reported 2 changed paths and 38
families; the clean derivation above reports 1 path and 37, the extra family
having been check:llms-txt matched via node_modules.

NOT MEASURED — named, and none of these is a pass or a finding:

exit commands why
3 check-aggregator-roster (+--self-test), check-closing-keyword-parity (+--self-test), check-merged-branch-reaper-outcome (+--self-test), check-step-collectors (+--self-test), check:pnpm-acquisition, check:required-contexts, check:shard-attestation, check:stall-guard-budget, check:stall-guard-headroom, check:workflow-status-functions PREREQUISITE NOT MET — the dependency 'yaml' is not installed
3 check:driver-memory-census PREREQUISITE NOT MET — the dependency 'typescript' is not installed
3 check:type-check-debt PREREQUISITE NOT MET — needs a built package closure, not built here
1 check-comment-mask-corpus Cannot find package '@typescript-eslint/parser' — a missing module, not a red gate
2 check-required-contexts --verify-required-set NOT VERIFIED — GET .../repos/objectstack-ai/objectstack answered HTTP 401; exit 2 classifies the ENVIRONMENT

The CI-parity family named in the dispatch, check-ci-filter-parity, is not in
the runnable list at all: the derivation scores it silent as an artifact
roster. check-closing-keyword-parity IS in the list and is yaml-blocked
above. Both run for real in CI.

Additional checks:

$ pnpm check:nul-bytes
EXIT=0
check-nul-bytes: OK (scanned 7610 text file(s) -- 7610 tracked, 0 untracked-not-ignored; ... no raw ASCII control bytes).

$ grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' .github/workflows/lint.yml
EXIT=1   (no match — no raw control bytes in the edited file)

$ node scripts/pm/check-governed-merges.mjs --test .github/workflows/lint.yml
EXIT=0
governed-surface predicate: 0 of 1 path(s) hit the register (5 surfaces, repo-agnostic).
  ✅  NOT governed — ordinary queue landing applies to a PR with exactly this file list.

No heavy verify was needed, so the shared verify lock was read (state: holder pid 5455) but never taken.

Changeset

None, and the skip-changeset label is the correct one by AGENTS.md's own rule,
quoted: "A bug fix in a released package takes a patch changeset — never none,
and ⛔ never skip-changeset: that label is for a diff that publishes nothing
from any released package."
A comments-only edit to a workflow publishes nothing
from any package.

Filed out of scope

Two observations that this card's rulings fence off, both filed bare (no labels,
no assignee) after a dedup sweep of 617 open items over the repo-scoped REST list
endpoint with a control word verified to hit:

🤖 Generated with Claude Code

https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk


Generated by Claude Code

The `PM half-state sweeper self-test` step claimed `extractWatchHints` over
`scripts/pm/check-half-states.mjs` yields "exactly ONE hint". It yields four,
and one of them — `.changeset`, from the noise-floor constant
`H36_SHARED_PREFIX_NOISE` — routes `pnpm check:pm-half-states` onto every
changeset-adding card. The reading is corrected, the "no pollution here"
half of the direct-entry argument is withdrawn, and the argument is restated
on the true reading: the routing costs one cheap offline self-test, not the
fan-out that forced a gate file next door.

The swallow-census step's block counted four declared control families with
three in `gated`. Seven are declared today and `gated` runs six. The count is
replaced by the family NAMES so the next family added contradicts a list
rather than an integer; the asymmetry argument (gated, never a bare
`--self-test`, because POSITIVE_CONTROLS pin members the repair programme
removes) is kept, and extended to say why the three newer cross-checks are
equally safe.

Comments only: the parsed YAML is identical to HEAD's.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
@claude

claude Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

ACCEPT — PR #15756 (head 95bf71449, .github/workflows/lint.yml +59/−16) reviewed against the GitHub three-dot diff, not the report.

Comments only: git diff -U0 … | grep -vE '^[-+]\s*#' prints nothing (PM seat re-ran it: empty). git merge-tree --write-tree clean against origin/main (a9b9c7dc9) and against the other seats' lint.yml PRs #15392 and #15331 (both EXIT=0).

Both readings re-measured by this seat on main:

Dev-filed follow-ups #15753 (noise-floor constant read as a hint — the class) and #15754 (the census script's own usage header carries the same stale arithmetic) are graded separately. skip-changeset read back present. NOT MEASURED here: the 14 yaml-blocked CI-parity gates and check:swallow-census-controls (no deps in this checkout); CI runs them.

Flip + arm when both required jobs report success on 95bf71449.


Generated by Claude Code

@claude

claude Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Flipped ready + auto-merge enabled (06:33Z, method: MERGE). Required jobs on 95bf71449: Lint & Repo Gates = success, TypeScript Type Check = success; git merge-tree --write-tree origin/main <branch> → EXIT=0 re-run against the current main. Watched; on landing #15537 and #15569 close.


Generated by Claude Code

@baozhoutao
baozhoutao added this pull request to the merge queue Sep 5, 2026
Merged via the queue into main with commit ef60224 Sep 5, 2026
31 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-15537-15569-lint-yml-stale-comments branch September 5, 2026 06:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants